#ifndef ROBOTCOMPONENT_H
#define ROBOTCOMPONENT_H

#include "global.h"

#include <cstdlib>
#include <QObject>
#include <QVector3D>
#include <QQuaternion>
#include <QStack>

#include "robotvisitor.h"

/**
 * @brief The basic element of a robot skeleton.
 *
 * The robot component class is a parent class for the joints and
 * segments of a robot.  Each component has some things in common,
 * such as dimensions and an offset from its parent.  A robot consists
 * of several components arranged in a heirarchical tree.  For example,
 * our Troy robot has a "body" component as its root, with a neck and
 * two shoulders as its children, and those have the head and arms
 * as their children, and so on.
 *
 * Each robot component implements the visitor pattern to allow for
 * easy traversal of the component tree.
 *
 * Each component can have an array of integer "names" associated with it.
 * They are used for openGL picking and can be used for other applications.
 *
*/
class RobotComponent : public QObject
{
    Q_OBJECT

public:
    //Constructors.  I did my best, but they are still a little ugly.
    RobotComponent(ComponentType type, NameGroup names, Dimension3D dimensions,
                   QString description = "", RobotComponent *parent = 0,
                   QVector3D offset = QVector3D(0,0,0), bool invertLength = false);

    RobotComponent(ComponentType type, NameGroup names, float radius,
                   QString description = "", RobotComponent *parent = 0,
                   QVector3D offset = QVector3D(0,0,0), bool invertLength = false);

    virtual ~RobotComponent();

    //Implements the visitor pattern with RobotVisitors
    virtual void accept(RobotVisitor *visitor);

    //Functions to get information about the component
    const unsigned int* names() const;
    ComponentType type() const;
    QVector3D offset() const;
    Dimension3D dimensions() const;
    bool inverted() const;
    QString description() const;

protected:
    ComponentType _type;
    unsigned int _names[MAX_NAMES];

    //Dimensions for the component
    Dimension3D _dimensions;
    //Offset from the parent component.  If there is no parent,
    //it is the offset from the origin <0,0,0>
    QVector3D _offset;

    //The length of the component is always assumed to be
    //along the -y axis, unless inverted is true, which
    //places length along the +y axis.
    bool _inverted;

    //Human-readable description for the component
    QString _description;

    //Returns a stack containing all the parents, grandparents, etc.
    //of this component.
    QStack<RobotComponent*> parentStack() const;
};

#endif // ROBOTCOMPONENT_H
